﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Cubicle.Nuget.Config;
using NuGet;

namespace Cubicle.Nuget.Core
{
    public static class PackageExtensions
    {
        private static NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();

        private static IEnumerable<INugetPackageFile> GetValidLibFiles(this IPackage package)
        {
            // Only install the lib files that are valid based on the criteria in the config file
            // TODO: Check installed .NET framework versions
            var dict = new Dictionary<string, Tuple<Version, IPackageFile>>(); // Dict filename -> Framework version -> full path
            var maxFramework = NugetConfig.Singleton.MaxFramework;
            var fileFramework = maxFramework;
            foreach (var file in package.GetLibFiles())
            {
                if (file.TargetFramework == null)
                {
                    fileFramework = maxFramework;
                }
                else if (file.TargetFramework.Identifier != maxFramework.Identifier)
                {
                    _logger.Debug("Skipping file, framework mismatch. Source = {0}, Target = {1}", file.TargetFramework.Identifier, maxFramework.Identifier);
                    continue;
                }
                else if (file.TargetFramework.Version > maxFramework.Version)
                {
                    _logger.Debug("Skipping file, version not supported. Source = {0}, Target = {1}",
                                  file.TargetFramework.Version, maxFramework.Version);
                    continue;
                }
                else
                {
                    fileFramework = file.TargetFramework;
                }
                var filename = Path.GetFileName(file.Path);
                if (!dict.ContainsKey(filename) || dict[filename].Item1 < fileFramework.Version)
                    dict[filename] = new Tuple<Version, IPackageFile>(fileFramework.Version, file);
            }
            return dict.Values.Select(x => new NugetPackageFile(package, x.Item2));
        }

        private static IEnumerable<INugetPackageFile> GetBinFiles(this IPackage package)
        {
            var contentFiles = package.GetContentFiles().Select(x => new NugetPackageFile(package, x));
            return package.GetValidLibFiles().Union(contentFiles);
        }

        public static bool UninstallFromBin(this IPackage package)
        {
            var success = true;
            foreach (var file in GetBinFiles(package).Where(file => file.IsInBin()))
            {
                if (file.RemoveFromBin())
                {
                    _logger.Info("File removed from Bin. Path = {0}", file.BinPath);
                }
                else
                {
                    _logger.Error("Failed to remove file from Bin. Path = {0}", file.BinPath);
                    success = false;
                }
            }
            return success;
        }

        public static bool InstallToBin(this IPackage package)
        {
            var binFiles = package.GetBinFiles();
            var inUse = binFiles.Where(x => x.IsInUse());
            if (inUse.Any())
            {
                foreach (var file in inUse)
                    _logger.Error("File in use. File = {0}", file.BinPath);
                return false;
            }

            var success = true;
            foreach (var file in binFiles)
            {
                if (file.CopyToBin())
                {
                    _logger.Info("File copied to Bin. Path = {0}", file.BinPath);
                }
                else
                {
                    _logger.Error("Failed to copy file to Bin. Path = {0}", file.BinPath);
                    success = false;
                }
            }

            if (success)
                _logger.Info("All package files copied to Bin folder.");

            return success;
        }

    }
}